#include "ModifiedBlowfish.h"

NAMESPACE_BEGIN(CryptoFBC)

const FBC_Dword MODIFYBLOWFISH::PBOX_init[18]={
	0xF35AF301, 0x4BA5308F, 0x3E78B787, 0x3B28EDC8, 0x5D9D9334, 0x69B78D4C, 
	0x6AA9CE9E, 0xE8DC9EF8, 0xAB3FA2AE, 0xA41A08D1, 0x182E4462, 0x7D6A8455, 
	0xEB85AD5D, 0x4051D52F, 0xA8C782C2, 0xD5E8EB10, 0x2F80CE14, 0x811C88D7
};

const FBC_Dword MODIFYBLOWFISH::SBOX_init[4][256]={
	0x4D0EF68C, 0xA107EBEE, 0xE3FF4CC5, 0x696DA9BE, 0xB4726BCF, 0x64B93DF4, 
	0xAC4670DD, 0x70D8739D, 0x241950F8, 0xAFEFB3BC, 0x6C658E56, 0xB14A27CA, 
	0x812CB4A2, 0x511450E7, 0xB5B1D1E7, 0xD5A43704, 0xA16C5ED6, 0x577B6B9D, 
	0x93F5E943, 0xABE60F53, 0x9E3B6D44, 0x8C782130, 0x3E24A84C, 0x02D77434, 
	0xC0B8B004, 0x691821A8, 0x8D1F6D3F, 0xBDD3FC4A, 0x1D6D9B5D, 0x7A0E7FA4, 
	0xB81D3335, 0x6E962A04, 0xBF28E4F4, 0xF3B3BFC6, 0x2BF1F6F2, 0xBE771D44, 
	0x8F82311A, 0xE0B34C85, 0xBAC55EA3, 0x90C3EF93, 0xD3521141, 0x01DCAA43, 
	0xE4F24252, 0x152770CE, 0x505710BC, 0x6D63AC64, 0x03311A7B, 0x3BCE665F, 
	0x08B326FB, 0xF8BFE2DD, 0xF281C30D, 0x4A52B6E1, 0xB42E2C02, 0x1F817127, 
	0xBDB0A48D, 0xE2D9BB55, 0xF64950F1, 0x3AE9CCE0, 0xC56D95DD, 0x98583217, 
	0xA8FB4DFA, 0x88B0BF5B, 0xFC79AA1B, 0xB4F351C0, 0x16D948C5, 0x33EE4813, 
	0x9279AF06, 0x649B2C07, 0x668B3F1D, 0x8DB14785, 0x0C680FE2, 0x552C21DC, 
	0xAA972C53, 0x5F7AFFA8, 0x9B049880, 0x2A7D9073, 0x4C350DBF, 0xE776E6D5, 
	0xE692FAF6, 0x28404CF7, 0x0D1DC86F, 0x44CE64AA, 0x662E83AB, 0x338C8671, 
	0xB1F6A028, 0xA32B60EA, 0x51540B84, 0x5D24F893, 0xDB9D605C, 0xD185A9C8, 
	0xC2534CC4, 0x21A1C0E3, 0xD3893F11, 0x17AF55AE, 0xAC7DB02C, 0x699D4E31, 
	0xAD591C44, 0x564FE117, 0x0FB550F8, 0x574FFFC1, 0x5F1F2D7C, 0x6D8B5DC1, 
	0xCE645E9A, 0x4CF591E4, 0x6FBB1847, 0x6B07294C, 0x05099F30, 0xC5D89086, 
	0xB01CAA6E, 0x341AB5CE, 0x70824F82, 0x09656017, 0x0BE0F9E8, 0x56603CCD, 
	0xB03E83D7, 0xB5351BDD, 0x2FA563CC, 0x95FC8CB8, 0xB45BF505, 0x924A21C5, 
	0x7EAEDB23, 0x71542651, 0xB6FCF946, 0x41C7725B, 0xC2F750CC, 0x90DAFDF2, 
	0xB1EEF4DA, 0x83C464A0, 0x8ED35FEF, 0x98BC3260, 0xD5FD0F38, 0x50A6091F, 
	0xB7B841C7, 0x4C1E4155, 0x727807D8, 0x37323CA5, 0xF9ACB934, 0xDECA8621, 
	0x7CF03A2C, 0xFF6D785D, 0xD78BFF18, 0x296308E4, 0x0A480656, 0xEBF31EC8, 
	0x3F90839E, 0xF031BE2F, 0x7F9AEBDC, 0x5CC86017, 0xC03AE15B, 0x6ADB9232, 
	0x972C53D6, 0x994E5CBF, 0x182214B1, 0x7F97FE28, 0x324C5280, 0xAB19ECD9, 
	0x8C7F2A06, 0x015D351C, 0x4BAFF748, 0xE1389F59, 0x6227EDA5, 0xC5DB77B0, 
	0x40E6080D, 0x1A697472, 0x507F0160, 0x109342D3, 0x7E6DE9CD, 0xFE9DBE44, 
	0xE442DBB8, 0x9C780F22, 0xC0B3EEF6, 0x958726AE, 0x6AA11481, 0xD7073473, 
	0xFA3B72CC, 0xA4889A8C, 0x037FFBEA, 0x5CC3FAF8, 0x6C29E70F, 0x24B5F2EC, 
	0x69BAA609, 0x8011F4E8, 0x8B835BFE, 0xE472D992, 0x2DA5EB04, 0x2EF33B44, 
	0xFE06C479, 0x60C50A31, 0xB24B8143, 0x40D72E36, 0x234241B0, 0x0707C1BE, 
	0x9E1FD60D, 0x9576C16A, 0xE80A6B41, 0x2B9C88B6, 0x6D7B1DF8, 0x8A2F744B, 
	0x76FA9455, 0x2A7218CE, 0x1ECC066E, 0x35CCCEA8, 0xB545F330, 0xAC1F74DA, 
	0x17403235, 0x34C8C544, 0xBF2BBB94, 0x0F95F3F9, 0x220CD5D4, 0x6C7E8664, 
	0x9BACD0A5, 0xC27ECF35, 0xB92EAA7C, 0x05FCC924, 0x8EAD91EB, 0x9C71B69D, 
	0x9DD55736, 0x07564ADB, 0xDE99CC9F, 0x6DBC45EB, 0xA55AF6B0, 0xE3A12201, 
	0x259A0C27, 0x4DDB16CD, 0x79F76BBD, 0xAF1D8B35, 0x7AECB0B0, 0xA0B9838B, 
	0x64FEB5E8, 0xC106FFAE, 0x904EC76F, 0x4A50647F, 0x5FF204DB, 0xA1FCE69F, 
	0x16AB2C81, 0xE67D0048, 0x8541CE3C, 0x1563C989, 0xC609B8BB, 0xFDC088F8, 
	0x3818ACDC, 0x305F84EE, 0x05646126, 0x568D1555, 0x9A5D071B, 0xC94DBAF1, 
	0xCEECDAE0, 0x811012A3, 0x8DB0D395, 0x2DDFE926, 0xB598FD32, 0x6CAD805C, 
	0x19F92F7D, 0x7DAB27EF, 0xD33117D7, 0x7E4EC3DB, 0xC946F2C5, 0xC2EF51A2, 
	0xF53D6BF2, 0xB8ECB059, 0xD7229F17, 0xDDD5D80A, 0x36EC9255, 0xF5C59B3F, 
	0x2CBF159F, 0x2632C17E, 0x0C892508, 0x008FD783, 0xFABC94E3, 0x7B0EB537, 
	0x08C78B03, 0x9549190A, 0x237CD448, 0x6F7181F2, 0xC9B8889E, 0x35351B2F, 
	0xE2499337, 0x708A0042, 0x9535A3AC, 0xC3C62B54, 0x9AB435FD, 0xD04DAE5D, 
	0x1C2AC642, 0xA839C24F, 0x89031EAB, 0x5C4A464F, 0x71D4C7B6, 0xC852432B, 
	0x44C1AEDA, 0xD99C1F1B, 0x14FAA9E7, 0xEEDD0312, 0xCD83E048, 0x0F0AA339, 
	0x64576846, 0xF90A6B43, 0xF431F7C1, 0xE0C22AB3, 0x49550497, 0x5B7DD0A6, 
	0x198F78B3, 0xCDEB691E, 0x987BB6D9, 0x74492E60, 0x3BA6A163, 0x3F641058, 
	0x24A7F312, 0x7026137C, 0x49A2F42F, 0x87124EB7, 0xCEE3143C, 0x941F95C4, 
	0xDEDA02E5, 0x4F9B67E6, 0x753159BE, 0x9CB34281, 0x87B6B02A, 0x86110297, 
	0x51D6D8D4, 0xDAF2D4E4, 0x8CED5053, 0xB21B84A1, 0x067ED11F, 0x71E771CD, 
	0x9F3A2BBC, 0x7357F2B7, 0xDE80DD18, 0x385BCC4A, 0x6FD5D14A, 0x3E6F92B6, 
	0x86E4649D, 0xD29C4144, 0x6F116A1A, 0xA21E8DBE, 0x97E44FCC, 0x7167AA45, 
	0x1AAF69CF, 0xF0D91F15, 0x73E260C1, 0xE43BAF85, 0xDA63B26A, 0x04A512EB, 
	0xF376199E, 0x45CA02B0, 0x7B8A34E5, 0x56E14146, 0x9EBB1CCE, 0x4C7DBBF6, 
	0xB8F09CD2, 0x092DA5C6, 0x9D8375A1, 0x4CCFD625, 0x685999B7, 0x72BB32DB, 
	0x7015EC52, 0xF13C5569, 0x485173D5, 0xFD971B62, 0x1FB50985, 0x12EC96A9, 
	0x3011BC99, 0x55D5F041, 0x772BF225, 0xB872B7F9, 0x20C0CEE7, 0xE1BB8A58, 
	0xF5F53010, 0x88E709EB, 0x6BB8A011, 0xE52C1EC1, 0x14D24C0D, 0x6FBFBE02, 
	0x410C5442, 0x9271842C, 0xE76C2447, 0x9553A3FA, 0xA994C1CF, 0x8B5D1819, 
	0xB9181662, 0x475A994C, 0x6165F4BF, 0x7949613F, 0x0A5F522B, 0xBED3236C, 
	0xDE262E9C, 0xF85DF040, 0xC96884EC, 0x4EC14016, 0xFC556A6B, 0x6DC75A35, 
	0x73540B41, 0x05461DF6, 0xAD5C5115, 0x1465F2BE, 0xBA7BA89E, 0x10953A1F, 
	0x644A28AC, 0x288C95AC, 0x92E28401, 0xC0CCBDBB, 0x7062D744, 0x228F87CE, 
	0x8B7EE88F, 0x2DF0AAB7, 0x5ED7A5C7, 0xFC288C85, 0x975902DD, 0xC0AA62B6, 
	0xFE583B40, 0x9B03DF3D, 0xA41A0FA2, 0xC38390A1, 0x64008F6E, 0x1B475E3C, 
	0x5CA3DA10, 0xFC0C0465, 0x2F578BA6, 0x462807AD, 0xC29C73D9, 0x75C84E9E, 
	0xDC6B914B, 0x95A30FB3, 0x4CE00F5C, 0x9241FE9F, 0x2619FCFD, 0xFA4C6C47, 
	0x22FD7345, 0x86AF4BAA, 0x61D87EC8, 0xDFDFEC6D, 0x9D26F0F6, 0x6F9CB037, 
	0x5E837E07, 0x3F36F331, 0x9C143C3C, 0x40C1D611, 0xFC2CB0E3, 0x5B55DA44, 
	0xB94DEC48, 0x745E7B14, 0xBCB957C9, 0x67752B98, 0xA753C81E, 0xCB18B360, 
	0xFFD1078D, 0xBFE4C389, 0xF3735CC2, 0x0FF62E35, 0xDCFB012A, 0x05A66F38, 
	0xA8718AE0, 0xAC6146FF, 0x6B5B35C0, 0x528DC3F8, 0xA2BBF3E1, 0x2EC767B1, 
	0xAC8B8FD8, 0x34D57A06, 0xC7550ED7, 0xFEB29B85, 0x44CA0B1C, 0x8849C28F, 
	0x84CB68A6, 0x1F02E307, 0x49182DCD, 0xFF1BB2CF, 0x72A247ED, 0x2C70AA8D, 
	0x07F105B9, 0xB03A47AE, 0x5A005244, 0xBCEFC8D1, 0x3A3F773C, 0x34967208, 
	0x558402F2, 0x27103605, 0xF38221B4, 0x48D6CAFC, 0xA2707F24, 0x86FED4DE, 
	0x1B7D7BFB, 0x926BE508, 0xF26E4001, 0x1FC7686D, 0x74883923, 0x27C4BD9D, 
	0xE39F7B15, 0xB6413882, 0xC129CF02, 0xF874D23F, 0x4103C0D7, 0xC9B02F6D, 
	0x9358BC28, 0x9D1B79F5, 0x0D682EBD, 0xFF4F2404, 0x5AC79E5A, 0x9110D349, 
	0xA27B8802, 0xC968BFA5, 0xAB18A9FE, 0x742ED9EC, 0xA8BD78F6, 0x6A8E9C83, 
	0x418A5B57, 0x02584EAE, 0xC93818BA, 0x6912EAB7, 0xF32EBA26, 0x49A4737C, 
	0xC8E58D6F, 0x92A1E494, 0x2A18DDE5, 0x843AAF13, 0x249A8405, 0x99C9B047, 
	0x56780156, 0x13898195, 0x715090A5, 0x87498F9B, 0x5E1406C3, 0xA549F47A, 
	0x121C0394, 0xA962577E, 0xCCFD7BFB, 0x6A6B8489, 0x7009741D, 0x7423F0E1, 
	0x299B3640, 0x74A6C8F9, 0x5780F8D9, 0xF667ED91, 0x2E04EB8B, 0xBFA152E5, 
	0x790C25CE, 0x4C06D6D7, 0xDBD6E036, 0xC5DD5F0D, 0x7B484C43, 0xB50F4087, 
	0x5C9214FA, 0xA0DDAE8E, 0xEF969A43, 0x52506920, 0x7534A46B, 0x2D27857D, 
	0x0AB95E75, 0xB3C3470E, 0x3B70729A, 0x066BF399, 0x169D2898, 0xE8D10DDA, 
	0x3ACA8857, 0xB49F5680, 0x9A6ADB21, 0x3C299C82, 0x1372417D, 0x24DB472A, 
	0xDAE0A8DA, 0xB8C7F985, 0x953293E9, 0x7D8B7E48, 0xF63344CE, 0x11556C31, 
	0x0387E185, 0x7DA8B975, 0xF3C5EEA3, 0x27E4214A, 0x9C626A45, 0x5B38528F, 
	0x3505B38F, 0xF5C6DA44, 0x53E880A7, 0x5B821531, 0xBB95A3EB, 0x44458D3E, 
	0x5D1B2D6A, 0x3FF103B7, 0x03185A8D, 0xDBEF4287, 0x10CAB115, 0xE5B7B622, 
	0x3B5518C3, 0x94B79DAC, 0x6AB0B259, 0x44601702, 0x96E4D041, 0x40D02422, 
	0xB398B382, 0x604BD277, 0xE8E8657A, 0x9D54FD02, 0x95EFB267, 0x97C1C4CB, 
	0x36E6C1C6, 0x2F2835F2, 0x3C3F9416, 0x65F598BE, 0x29AC4225, 0x6B2B762B, 
	0xC4758FEB, 0xBD0D781C, 0x259E9059, 0x674C390D, 0x4C310667, 0xDAF0E64F, 
	0xB19823A9, 0xA71472E4, 0xE9A592A5, 0x8F816B69, 0x7D218862, 0x09A29029, 
	0xD27DFC54, 0x9197281F, 0x77DF087D, 0x58C9268A, 0xE511B314, 0x42002725, 
	0xE96C2D4B, 0x833EF5D8, 0x5D1A581D, 0xFCCD96EB, 0x19A2F0B9, 0x07230D54, 
	0x190E163A, 0x33805ECC, 0x7AD05B9D, 0x5A65633C, 0x38BD084B, 0x5D468C7B, 
	0xE81D907F, 0x183A772C, 0x16230189, 0x75524F97, 0x76846132, 0x66550E65, 
	0x09CC68DE, 0x8670A3B1, 0xFF25C5A9, 0x09D52BFE, 0x0F8043DF, 0x1B1770FB, 
	0x107EF3A1, 0x776F1EB6, 0x5257EDB1, 0x2C55FEA7, 0xA980E375, 0xAE9DC4CF, 
	0x0B25500A, 0x92C525DB, 0x18D0DC79, 0x1789F171, 0xB3DBD50F, 0x828647D5, 
	0x0242F4B5, 0x8920E4A6, 0xD2EB0C2B, 0xF78760BC, 0xB619630F, 0xE23E87C7, 
	0xBB9EB076, 0x46DD96A8, 0x42616BB3, 0x2353D9E7, 0xD76D8B3B, 0x1594CCDE, 
	0xD076CD86, 0x124FD79A, 0xD7D4F3E3, 0x59D4EB4E, 0xFB9B0548, 0x19AEF54D, 
	0xEA942CD1, 0xA8416A0C, 0x68407891, 0xFF5FF7CC, 0xFDD03622, 0x74CB2995, 
	0xB904C6A6, 0x8DD1426A, 0x111C3EA3, 0x208E1721, 0xAEC46415, 0x829EBC0B, 
	0x0435361D, 0x7CB6A164, 0x56984149, 0xE8B03E7B, 0x5079E086, 0x32CF6958, 
	0x29AA490A, 0xE70F7A3A, 0x928866AE, 0xE000A933, 0x301A87F4, 0x1CC2A6A6, 
	0xFCEC043B, 0x73256424, 0x4DD63DF5, 0xBE9F0C5D, 0xC236863B, 0x33AAD8F1, 
	0x8F1AC131, 0x74B00667, 0x90A9756F, 0x82275100, 0xC2433597, 0x99A73E00, 
	0x9CC8C8AF, 0x492CBCB8, 0x3341EE98, 0x875205CA, 0xD0A4274F, 0x0A33E18C, 
	0x50625F8A, 0xD34C3CBE, 0x784C07E2, 0x85386527, 0x0D19B3B2, 0x00B53905, 
	0x9099D185, 0x6AD4470C, 0x6BDB5049, 0x6AB57ED7, 0xCE1DAC58, 0xF51F9E54, 
	0x38FBF949, 0x627978CA, 0x8C92078F, 0xE437AED9, 0xEA546852, 0xF10212FC, 
	0x78779F55, 0x98B11998, 0x21547487, 0x637F3BDF, 0xD103BC7F, 0x086F3355, 
	0x71E52401, 0x41A183EE, 0x3D3426DA, 0xA5CCAF0A, 0x4077EF65, 0x51A2B63D, 
	0x6143052C, 0x7331481D, 0xF051ABFD, 0x1A9B500D, 0x241C24CA, 0x6E575567, 
	0x61F1BA79, 0x37473434, 0x3350ED06, 0x2C61D57C, 0x7304FABE, 0x05284A24, 
	0x67E580FB, 0xE9EF975A, 0xFDE3C1B0, 0x10AC3476, 0x7F664147, 0x3C2B2522, 
	0xE2BA00B5, 0xD958510A, 0x4C4D901A, 0x7D300E2B, 0x43027577, 0x976E17AE, 
	0x02212E53, 0x48DF9542, 0x3D8B1E58, 0xB5A73013, 0xE75BE3AB, 0xD59A2437, 
	0x6DA276F1, 0xB6C60643, 0xF75DA229, 0xA4E8CF63, 0xFBFFF2E3, 0x173A9350, 
	0x8112BD74, 0x42EB77DB, 0x53B0DD89, 0xBBF012EE, 0xFD23F8F4, 0xFACE82EC, 
	0x410F43BE, 0xA0775E51, 0x0F30F01C, 0x3383D52B, 0x754185DA, 0x43645320, 
	0x0CA4B18D, 0xC7282FAA, 0x27FA8310, 0x98CB7A47, 0x75B3AE87, 0x30E601DF, 
	0xA448BF37, 0x6D9317BD, 0x0EFECC6A, 0x4BC684B3, 0x67872997, 0x4580376E, 
	0x95C9BD47, 0xD38EF86C, 0xF36F0102, 0x0F83E5A9, 0xF192A394, 0x85ABA799, 
	0x7D3D8570, 0xB0450768, 0x57F416F9, 0x11FE6A11, 0x5D51C79A, 0xE83BFBFC, 
	0xFB3F8427, 0x9DB2E430, 0xC96F898E, 0x5D2AEC92, 0x5281FDCF, 0x3E08AC4D, 
	0x5AE5DEF7, 0x48738A22, 0xB073272B, 0x540FEE81, 0xBE7B6503, 0x1C9698AF, 
	0xF5E4BF76, 0x8E648E58, 0xDDF14830, 0xC6F786E0, 0x906220C3, 0x62A42F93, 
	0x72885584, 0x3403F677, 0x3C541144, 0x28818CDC, 0xA28DA089, 0x528CA22F, 
	0x8659521E, 0xBCB214EF, 0xCD950AA8, 0xBFF61551, 0x414A27B8, 0x1A0E7B95, 
	0x39E83CC3, 0x4F567DA4, 0x613C72E7, 0xF0514CC9, 0x21E1FF1C, 0xE139A5CD, 
	0x6F9E1D4B, 0x2B768EB9, 0x8316BA1C, 0xAC98CD48, 0xEE51C7B6, 0x626B9819, 
	0xEBE64D96, 0x34053FB1, 0xC7F2290C, 0xF1144E7A, 0x655A67C2, 0xDBC6CB12, 
	0xDE46EDE9, 0xBF45BD71, 0x96AF6C36, 0x4DF19BD4, 0x5602402B, 0x201DED42, 
	0xFB8CE6E3, 0xEEE82171, 0xBA4337D2, 0xBBE88FF2, 0xC8EB5309, 0x2D80AB73, 
	0x447A35D2, 0xF5A964C3, 0x5270C6D2, 0x1E74AE1C, 0x597B5E54, 0x106151BB, 
	0xA6CC9A31, 0xD74B1A9B, 0x8101FAB3, 0x5B338459, 0x6BB4A4AC, 0x50A5D796, 
	0x098867C6, 0xAFBC968B, 0x86A0A06A, 0xE5FAA862, 0xF5EE732A, 0x438EEC58, 
	0x4FA41DDC, 0x37E5C456, 0x9980812A, 0x49BD86EE, 0xAC80ED8C, 0xF188D578, 
	0x6EAB6CCB, 0x89D8637F, 0x77EC8ED8, 0x18E199CE, 0x07FD5BC7, 0x4D06E4EA, 
	0x53112753, 0xD3F01924, 0x9A5A9BF2, 0x3D2D01CE, 0xC8898AAF, 0x61C78512, 
	0xA5F87B41, 0x088D2629, 0xFE0A19D6, 0x8B5E091B, 0x32F5B20D, 0x4A6C0B63, 
	0x4B1AF4D7, 0xB2314CD0, 0x37B58D37, 0x25C8E1C6, 0x4E57387B, 0x4CEAB46D, 
	0x424570EC, 0x76FFD418, 0x1DDF4F36, 0x6A94CF16, 0x9487F38B, 0xD0FFD93D, 
	0x2AC2324A, 0x944B923A, 0x7797D0F5, 0xA9FDAACD, 0x3E6DA87B, 0xCF8D6C77, 
	0xAB30CDC3, 0xF9AB590B, 0x8E7CC17D, 0xD1402605, 0x670CD719, 0xECED6126, 
	0x967D5428, 0xA09DF8CD, 0x9CAAED21, 0x16CAD2D2, 0x14DB0BCF, 0x561F1431, 
	0xC391D5BA, 0x28CA012C, 0x20157324, 0x654DC34E, 0x68662B7D, 0x4B3F487F, 
	0xD89E5304, 0x06B8E74A, 0x54A6E133, 0x61923326, 0xB008BDA2, 0x0CD5BF8E, 
	0x0A8220CC, 0x53CD765C, 0xFF8F5210, 0x58E1043F, 0xE108B0FE, 0x3D58E542, 
	0x855613CD, 0x57F5323A, 0xB14D9999, 0x4523DEE3, 0x0BA85373, 0xE29F2AA3, 
	0xDD427664, 0x7EBE5925, 0x7094E452, 0x73B7DC52, 0xDB598DCB, 0x2E1620BE, 
	0x7E7DE24A, 0xDB374056, 0xB7234E51, 0xE708123B, 0x66A54C25, 0xBBA5E279, 
	0xADB044FD, 0x5832B4F6, 0x95825E3F, 0x6730497A, 0x1D23A8FA, 0xF3945228, 
	0x799E02BD, 0xE6A5E5A5, 0xE38E0E7A, 0x65C2FE14, 0x21C99A8D, 0x9438B8F6, 
	0xA7D347FE, 0x5CA19AD6, 0xE1C2C9A3, 0xB2B28AF4, 0x1D91ECF4, 0x39A3F962, 
	0xDD38FBD0, 0x16802910, 0x0217E00B, 0x557F0861, 0x1AC5C32A, 0x19F3B8B0, 
	0x2949C312, 0x928F1BBB, 0x47B895FE, 0xD05FAE3A, 0xE62DD85C, 0x16971C70, 
	0x565A1F77, 0x63CBC20E, 0x582B9409, 0xA8130DC9, 0x271D3821, 0x741412AC, 
	0xD250A0AA, 0x6023039C, 0xB1DDA950, 0xABB80431
};

const int MODIFYBLOWFISH::BLOCKSIZE=8;
const int MODIFYBLOWFISH::ROUNDS=16;

void MODIFYBLOWFISH::SetKey(CipherDir dir,const FBC_Byte* keystring,FBC_Word keylength)
{
	unsigned i = 0;
	unsigned j = 0;
	unsigned k = 0;
	FBC_Dword dwtemp1 = 0;
	FBC_Dword dwtempdata[2] = {0, 0};
	FBC_Dword dwdata[2] = {0, 0};
	
	if ( Inited == false )
	{
		memcpy_FBC(PBOX_var,PBOX_init,sizeof(PBOX_init));
		memcpy_FBC(SBOX_var,SBOX_init,sizeof(SBOX_init));
		
		for(i=0;i<ROUNDS+2;i++)
		{
			dwtemp1=0;
			for(j=0;j<4;++j)
			{
				dwtemp1=((dwtemp1<<8)|keystring[k++ % keylength]);
			}
			PBOX_var[i]^=dwtemp1;
		}
		
		for(i=0;i<ROUNDS+2;i+=2)
		{
			ECB_Encryption(dwdata,dwtempdata);
			PBOX_var[i]=dwdata[0]=dwtempdata[0];
			PBOX_var[i+1]=dwdata[1]=dwtempdata[1];
		}
		
		for(i=0;i<4;i++)
		{
			for(j=0;j<256;j+=2)
			{
				ECB_Encryption(dwdata,dwtempdata);
				SBOX_var[i][j]=dwdata[0]=dwtempdata[0];
				SBOX_var[i][j+1]=dwdata[1]=dwtempdata[1];
			}
		}
		Inited = true;
	}
		
	if ( dir != enumLastDir)
	{
		for(i=0;i<(ROUNDS+2)/2;i++)
		{
			swap(PBOX_var[i],PBOX_var[ROUNDS+1-i]);
		}
		enumLastDir = dir;
	}
}

inline FBC_Dword MODIFYBLOWFISH::mF(FBC_Dword x) const
{
	FBC_Word a,b,c,d;
	FBC_Dword y;

	d=FBC_Word(x&0x00FF);
	x>>=8;
	c=FBC_Word(x&0x00FF);
	x>>=8;
	b=FBC_Word(x&0x00FF);
	x>>=8;
	a=FBC_Word(x&0x00FF);
	y=SBOX_var[0][a]+SBOX_var[1][b];
	y^=SBOX_var[2][c];
	y+=SBOX_var[3][d];
	return y;
}

void MODIFYBLOWFISH::ECB_Encryption(const FBC_Dword inblock[2],FBC_Dword outblock[2]) const
{
	FBC_Dword dwLeft,dwRight,dwTemp;
	unsigned i;

	dwLeft=inblock[0];
	dwRight=inblock[1];
	_asm
	{
		pushad;
		mov ecx,DWORD PTR [dwLeft];
		mov eax,ecx;
		shr eax,8;
		mov edx,ecx;
		shl edx,8;
		xor eax,edx;
		and eax,0x00FF00FF;
		shl ecx,8;
		xor eax,ecx;
		rol eax,16;
		mov DWORD PTR [dwLeft],eax;
		xor ecx,ecx;
		xor eax,eax;
		xor edx,edx;
		mov ecx,DWORD PTR [dwRight];
		mov eax,ecx;
		shr eax,8;
		mov edx,ecx;
		shl edx,8;
		xor eax,edx;
		and eax,0x00FF00FF;
		shl ecx,8;
		xor eax,ecx;
		rol eax,16;
		mov DWORD PTR [dwRight],eax;
		popad;
	}
	
	dwLeft^=PBOX_var[0];
	for(i=0;i<8;i++)
	{
		dwTemp=mF(dwLeft);
		dwTemp^=PBOX_var[i*2+1];
		dwRight^=dwTemp;
		dwTemp=mF(dwRight)^PBOX_var[i*2+2];
		dwLeft^=dwTemp;
	}
	dwRight^=PBOX_var[ROUNDS+1];

	_asm
	{
		pushad;
		mov ecx,DWORD PTR [dwRight];
		mov eax,ecx;
		shr eax,8;
		mov edx,ecx;
		shl edx,8;
		xor eax,edx;
		and eax,0x00FF00FF;
		shl ecx,8;
		xor eax,ecx;
		rol eax,16;
		mov DWORD PTR [dwRight],eax;
		xor ecx,ecx;
		xor eax,eax;
		xor edx,edx;
		mov ecx,DWORD PTR [dwLeft];
		mov eax,ecx;
		shr eax,8;
		mov edx,ecx;
		shl edx,8;
		xor eax,edx;
		and eax,0x00FF00FF;
		shl ecx,8;
		xor eax,ecx;
		rol eax,16;
		mov DWORD PTR [dwLeft],eax;
		popad;
	}

	outblock[0]=dwRight;
	outblock[1]=dwLeft;
}

void MODIFYBLOWFISH::SetIV(const char* strIV, int nLen)
{
	int i = 0;
	int n = 0;
	char* p = (char*)&dwInitialVector;

	n = (nLen > 8) ? 8 : nLen;

	memset_FBC((char*)&dwInitialVector, 0, 8);

	for ( i = 0; i < n; i++ )
	{
		p[ i ] = strIV[ i ];
	}
}

bool MODIFYBLOWFISH::CBC_Encryption(const char* pIn, 
									int nInLen, 
									char* pOut, 
									int* nOut 
									)
{
	FBC_Dword dwLoopVar = 0;
	FBC_Dword dwLen = 0;
	FBC_Dword* pdwIn = NULL;
	FBC_Dword* pdwOut = NULL;
	FBC_Dword dwTemp[ 2 ] = { 0 };
	FBC_Dword dwResult[ 2 ] = { 0 };

	FBC_PROCESS_POINTER(pIn);
	FBC_PROCESS_POINTER(nOut);
	if ( nInLen <= 0 )
	{
		goto Exit0;
	}
	if ( pOut == NULL )
	{
		dwLen = FBC_Dword(nInLen) & 7;
		if ( dwLen == 0 )
		{
			*nOut = nInLen;
		}
		else
		{
			*nOut = nInLen + FBC_Dword( 8 - dwLen );
		}
		goto Exit1;
	}
	if ( *nOut <= 0 )
	{
		goto Exit0;
	}

	dwLen = FBC_Dword(nInLen) & 7;
	if ( dwLen == 0 )
	{
		dwLen = nInLen;
	}
	else
	{
		dwLen = nInLen + FBC_Dword( 8 - dwLen );
	}
	if ( FBC_Dword(*nOut) < dwLen )
	{
		goto Exit0;
	}

	dwLen >>= 2;

	pdwIn = new FBC_Dword[dwLen];
	FBC_PROCESS_POINTER(pdwIn);
	memset_FBC(pdwIn, 0, dwLen);
	memcpy_FBC((char*)pdwIn, pIn, nInLen);
	pdwOut = (FBC_Dword*)pOut;
	dwTemp[ 0 ] = dwInitialVector[ 0 ];
	dwTemp[ 1 ] = dwInitialVector[ 1 ];

	for ( dwLoopVar = 0; dwLoopVar < dwLen; dwLoopVar += 2 )
	{
		dwResult[ 0 ] = pdwIn[ dwLoopVar ] ^ dwTemp[ 0 ];
		dwResult[ 1 ] = pdwIn[ dwLoopVar + 1 ] ^ dwTemp[ 1 ];
		ECB_Encryption(dwResult, &pdwOut[ dwLoopVar ]);
		dwTemp[ 0 ] = pdwOut[ dwLoopVar ];
		dwTemp[ 1 ] = pdwOut[ dwLoopVar + 1];
	}
	*nOut = dwLen << 2;
Exit1:
	delete[] pdwIn;
	return true;
Exit0:
	return false;
}

bool MODIFYBLOWFISH::CBC_Decryption(const char* pIn, 
									int nInLen, 
									char* pOut, 
									int* nOut 
								)
{
	FBC_Dword dwLen = 0;
	FBC_Dword dwLoopVar = 0;
	FBC_Dword dwTemp[ 2 ] = { 0 };
	FBC_Dword* pdwIn = NULL;
	FBC_Dword* pdwOut = NULL;

	FBC_PROCESS_POINTER(pIn);
	FBC_PROCESS_POINTER(nOut);
	if ( nInLen <= 0 )
	{
		goto Exit0;
	}
	if ( pOut == NULL )
	{
		dwLen = FBC_Dword(nInLen) & 7;
		if ( dwLen == 0 )
		{
			*nOut = nInLen;
		}
		else
		{
			*nOut = nInLen + FBC_Dword( 8 - dwLen );
		}
		goto Exit1;
	}
	if ( *nOut <= 0 )
	{
		goto Exit0;
	}

	dwLen = FBC_Dword(nInLen) & 7;
	if ( dwLen == 0 )
	{
		dwLen = nInLen;
	}
	else
	{
		dwLen = nInLen + FBC_Dword( 8 - dwLen );
	}
	if ( FBC_Dword(*nOut) < dwLen )
	{
		goto Exit0;
	}

	pdwIn = new FBC_Dword[dwLen >> 2];
	FBC_PROCESS_POINTER(pdwIn);
	memset_FBC(pdwIn, 0, dwLen);
	memcpy_FBC((char*)pdwIn, pIn, nInLen);
	pdwOut = (FBC_Dword*)pOut;
	dwTemp[ 0 ] = dwInitialVector[ 0 ];
	dwTemp[ 1 ] = dwInitialVector[ 1 ];

	for ( dwLoopVar = 0; dwLoopVar < ( dwLen >> 2 ); dwLoopVar += 2 )
	{
		ECB_Encryption( &pdwIn[ dwLoopVar ], &pdwOut[ dwLoopVar ] );
		pdwOut[ dwLoopVar ] ^= dwTemp[ 0 ];
		pdwOut[ dwLoopVar + 1 ] ^= dwTemp[ 1 ];
		dwTemp[ 0 ] = pdwIn[ dwLoopVar ];
		dwTemp[ 1 ] = pdwIn[ dwLoopVar + 1 ];
	}
	*nOut = dwLen;
Exit1:
	delete[] pdwIn;
	return true;
Exit0:
	return false;
}

NAMESPACE_END